"""\
Ce que c'est
"""

import os, shutil, sys, errno
import urllib, cStringIO
import math
from statlib import stats
from PIL import Image, ImageFilter
import xml.dom.minidom
from optparse import OptionParser

ws_base_url = "http://192.168.0.16:8080/geoserver/ows?service=GeoCoverageWS&version=1.0.0&"


def ve_aerial_hasphoto(im): #242 is empty grey of virtual earth
    histo = im.convert("L").getcolors()
    for x in xrange(len(histo)):
        if(histo[x][1] == 242 and histo[x][0] > im.size[0]*im.size[1]*0.80): return False
    return True

def ym_aerial_hasphoto(im): #204 is empty grey of yahoo maps
    histo = im.convert("L").getcolors()
    for x in xrange(len(histo)):
        if(histo[x][1] == 204 and histo[x][0] > im.size[0]*im.size[1]*0.80): return False
    return True

def map_hasstreetname(im):
    if im.mode != "RGB": im = im.convert("RGB")
    pix = im.load()
    histo = []
    for y in xrange(im.size[1]):
        c = 0
        for x in xrange(im.size[0]): 
            if max(pix[x,y]) < 128: c = c + 1 #Search for dark pixel using max(r,g,b) (protects from bright blue/red roads)
        histo.append(c)
    histo.sort()
    del histo[int(len(histo)*0.95):len(histo)]
#    print "Average: "+str(sum(histo)*1.0/len(histo))
#    print "StdDev: "+str(stats.stdev(histo)/math.sqrt(len(histo)))
    return sum(histo)*1.0/len(histo)>1.5 and stats.stdev(histo)/math.sqrt(len(histo)) < 0.5

def map_hasstreet(im):
    if im.mode != "L": im = im.convert("L")
    im = im.filter(ImageFilter.FIND_EDGES)  
    pix = im.load()
    histo = []
    for y in xrange(im.size[1]):
        c = 0
        for x in xrange(im.size[0]): 
            if pix[x,y] > 64: c = c + 1 #Count edges pixels
        histo.append(c)
    return sum(histo)*1.0/len(histo)>20 and stats.stdev(histo)/math.sqrt(len(histo)) < 5
    
    
if __name__ == '__main__':
    parser = OptionParser("usage: %prog action")
    parser.add_option("-d", "--url", action="store", type="string", dest="url", 
        help="Download a single image from provided url for testing purpose")
    parser.add_option("-w", "--webservices", action="store", type="string", dest="basepath", 
        help="Process from webservices, caching tiles in provided directory")
    parser.add_option("-s", "--selftest", action="store_true", dest="selftest", 
        help="Selftest the tile analysis tuning on reference tiles")
    (options, args) = parser.parse_args()
            
    if options.selftest:
        print "-----------------------------------------------------------------"
        print "--Virtual Earth Tests"
        print "tile without photo"
        assert not ve_aerial_hasphoto(Image.open(cStringIO.StringIO(urllib.urlopen("http://a1.ortho.tiles.virtualearth.net/tiles/a120223030210330111.jpeg?g=234").read())))
        print "tile with photo"
        assert ve_aerial_hasphoto(Image.open(cStringIO.StringIO(urllib.urlopen("http://a2.ortho.tiles.virtualearth.net/tiles/a12022303021031302.jpeg?g=234").read())))
        print "@nice Orange street and railroad"
        assert map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://r1.ortho.tiles.virtualearth.net/tiles/r1202230302123321.png?g=234").read())))
        assert map_hasstreet(Image.open(cStringIO.StringIO(urllib.urlopen("http://r1.ortho.tiles.virtualearth.net/tiles/r1202230302123321.png?g=234").read())))
        print "@nice yellow streets  "      
        assert map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://r3.ortho.tiles.virtualearth.net/tiles/r1202230302123333.png?g=234").read())))
        assert map_hasstreet(Image.open(cStringIO.StringIO(urllib.urlopen("http://r3.ortho.tiles.virtualearth.net/tiles/r1202230302123333.png?g=234").read())))
        print "@nice sea"
        assert map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://r2.ortho.tiles.virtualearth.net/tiles/r1202230302301022.png?g=234").read())))
        assert map_hasstreet(Image.open(cStringIO.StringIO(urllib.urlopen("http://r2.ortho.tiles.virtualearth.net/tiles/r1202230302301022.png?g=234").read())))
        print "@timbuktu"
        assert not map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://r2.ortho.tiles.virtualearth.net/tiles/r033311233321132.png?g=234").read())))
        assert not map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://r0.ortho.tiles.virtualearth.net/tiles/r033311233321130.png?g=234").read())))
        assert not map_hasstreet(Image.open(cStringIO.StringIO(urllib.urlopen("http://r2.ortho.tiles.virtualearth.net/tiles/r033311233321132.png?g=234").read())))
        assert not map_hasstreet(Image.open(cStringIO.StringIO(urllib.urlopen("http://r0.ortho.tiles.virtualearth.net/tiles/r033311233321130.png?g=234").read())))
        print "-----------------------------------------------------------------"
        print "--Google maps Tests"
        print "@Africa"
        assert not map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://mt0.google.com/mt?v=w2.89&hl=fr&x=33540&s=&y=31282&z=16&s=Galile").read())))
        assert not map_hasstreet(Image.open(cStringIO.StringIO(urllib.urlopen("http://mt0.google.com/mt?v=w2.89&hl=fr&x=33540&s=&y=31282&z=16&s=Galile").read())))
        print "@South America"
        assert not map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://mt0.google.com/mt?v=w2.89&hl=fr&x=10218&s=&y=22211&z=15&s=G").read())))
        assert not map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://mt0.google.com/mt?v=w2.89&hl=fr&x=10218&s=&y=22211&z=15&s=G").read())))
        print "@philadelphia"
        assert map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://mt1.google.com/mt?v=w2.89&hl=fr&x=9543&s=&y=12411&z=15&s=").read())))
        assert map_hasstreet(Image.open(cStringIO.StringIO(urllib.urlopen("http://mt1.google.com/mt?v=w2.89&hl=fr&x=9543&s=&y=12411&z=15&s=").read())))
        print "-----------------------------------------------------------------"
        print "--Yahoo Maps Tests"
        print "tile without photo"
        assert not ym_aerial_hasphoto(Image.open(cStringIO.StringIO(urllib.urlopen("http://us.maps3.yimg.com/aerial.maps.yimg.com/ximg?v=1.9&t=a&s=256&x=8539&y=335&z=4").read())))
        print "tile with photo"
        assert ym_aerial_hasphoto(Image.open(cStringIO.StringIO(urllib.urlopen("http://us.maps3.yimg.com/aerial.maps.yimg.com/ximg?v=1.9&t=a&s=256&x=4267&y=169&z=5").read())))
        print "@nice yellow streets"      
        assert map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://us.maps2.yimg.com/us.tile.maps.yimg.com/tl?v=4.2&x=17047&y=4430&z=3").read())))
        assert map_hasstreet(Image.open(cStringIO.StringIO(urllib.urlopen("http://us.maps2.yimg.com/us.tile.maps.yimg.com/tl?v=4.2&x=17047&y=4430&z=3").read())))
        print "@oman with street without names"
        assert not map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://us.maps1.yimg.com/us.tile.maps.yimg.com/tl?v=4.2&x=21800&y=2110&z=3").read())))
        assert map_hasstreet(Image.open(cStringIO.StringIO(urllib.urlopen("http://us.maps1.yimg.com/us.tile.maps.yimg.com/tl?v=4.2&x=21800&y=2110&z=3").read())))
        print "@oman no coverage"
        assert not map_hasstreetname(Image.open(cStringIO.StringIO(urllib.urlopen("http://us.maps2.yimg.com/us.tile.maps.yimg.com/tl?v=4.2&x=21801&y=2107&z=3").read())))
        assert not map_hasstreet(Image.open(cStringIO.StringIO(urllib.urlopen("http://us.maps2.yimg.com/us.tile.maps.yimg.com/tl?v=4.2&x=21801&y=2107&z=3").read())))
    elif options.basepath:
        basepath = options.basepath
        if basepath[-1]!="\\": basepath = basepath+ "\\"
        while True:
            instream = urllib.urlopen(ws_base_url+"request=NextTilesWS")
            doc = xml.dom.minidom.parse(instream)
            for node in doc.getElementsByTagName("tiles"):
                guid = node.getAttribute("guid")
                zoomlevel = node.getAttribute("zoomlevel")
                maptype = node.getAttribute("maptype")
                alltiles = node.getAttribute("tilesurl").split("|")

                if not os.path.exists(basepath + guid):
                    os.mkdir(basepath + guid )
                    
                if maptype == "a":
                    nb_aerial=0;
#Count tiles with aerial coverage
                    for tileurl in alltiles:
                        print tileurl
                        instream = urllib.urlopen(tileurl, proxies = {'http': 'http://192.168.0.16:3128'})
                        filetype = instream.info().getheader("Content-Type")
                        if filetype != "image/png" and filetype!="image/jpeg" and filetype!="image/gif":
                            print "Invalid image type: "+filetype
                        else:
                            st = instream.read();
                          
                            ff=open(basepath + guid + "\\" + zoomlevel + maptype + "_" + str(hash(tileurl)) + "." + filetype.split("/")[1],'wb+')
                            ff.write(st)
                            ff.close()
                            
                            im=Image.open(cStringIO.StringIO(st))                        
                            if ve_aerial_hasphoto(im): 
                                nb_aerial = nb_aerial + 1
#Send result to server
                    instream = urllib.urlopen(ws_base_url + "request=WriteResDatabase&GID="+guid+"&ZoomLevel="+zoomlevel+"&MapType=a&CovCode=1&CovValue="+str(nb_aerial*1.0/len(alltiles))+"&EndProcess=1")
                    result = instream.read()
                    instream.close()
                    if result == "OK\n":
                        print "Update successful"
                    else:
                        print "Update failed !"                
                    
                if maptype == "r":
                    nb_tiles_withstreets = 0
                    nb_tiles_withstreetnames = 0
                    for tileurl in alltiles:
                        print tileurl
                        instream = urllib.urlopen(tileurl, proxies = {'http': 'http://192.168.0.16:3128'})
                        filetype = instream.info().getheader("Content-Type")
                        if filetype != "image/png" and filetype!="image/jpeg" and filetype!="image/gif":
                            print "Invalid image type: "+filetype
                        else:   
                            st = instream.read();
                          
                            ff=open(basepath + guid + "\\" + zoomlevel + maptype + "_" + str(hash(tileurl)) + "." + filetype.split("/")[1],'wb+')
                            ff.write(st)
                            ff.close()
                            
                            im=Image.open(cStringIO.StringIO(st))
                            if map_hasstreetname(im): 
                                nb_tiles_withstreetnames = nb_tiles_withstreetnames + 1 
                            if map_hasstreet(im): 
                                nb_tiles_withstreets = nb_tiles_withstreets + 1
#Send result to server
                    instream = urllib.urlopen(ws_base_url + "request=WriteResDatabase&GID="+guid+"&ZoomLevel="+zoomlevel+"&MapType=r&CovCode=7&CovValue="+str(nb_tiles_withstreets*1.0/len(alltiles))+"&EndProcess=0")
                    result = instream.read()
                    instream.close()
                    if result == "OK\n":
                        instream = urllib.urlopen(ws_base_url + "request=WriteResDatabase&GID="+guid+"&ZoomLevel="+zoomlevel+"&MapType=r&CovCode=8&CovValue="+str(nb_tiles_withstreetnames*1.0/len(alltiles))+"&EndProcess=1")
                        result = instream.read()
                        instream.close()
                        if result == "OK\n":
                            print "Update successful"
                        else:
                            print "Update for street names failed !"                
                    else:
                        print "Update for streets failed !"  
                        
                    
    elif options.url:
# fetch image from internet , check content-type
        instream = urllib.urlopen(options.url, proxies = {'http': 'http://192.168.0.16:3128'})
        filetype = instream.info().getheader("Content-Type")
        if filetype != "image/png" and filetype!="image/jpeg" and filetype!="image/gif":
            print "Invalid image type: "+filetype
#open image
        im = Image.open(cStringIO.StringIO(instream.read()))
    else:
        parser.print_help()
        sys.exit(1)


    

